public class IPv4Address {
    private static final int OCTETS_IN_ADDRESS = 4;
    private static final int BITS_IN_BYTE = 8;
    private static final int OCTET_MAX_VALUE = 255;
    private int[] hexConstants = new int[] {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF};
    private int intAddress;
    private String strAddress;

    public IPv4Address(String address) throws InvalidIpAddressException {
        validateIp(address);
        this.intAddress = ipToInt(address);
        this.strAddress = address;
    }

    public IPv4Address(int address) {
        this.intAddress = address;
        this.strAddress = ipToString(address);
    }

    public int getIntAddress() {
        return this.intAddress;
    }

    @Override
    public String toString() {
        return this.strAddress;
    }

    private void validateIp(String address) throws InvalidIpAddressException {
        String[] stringAddress = address.split("\\.");;
        int octetValue = 0;

        if ( stringAddress.length != OCTETS_IN_ADDRESS ) {
            throw new InvalidIpAddressException();
        }
        for ( int index = 0; index < OCTETS_IN_ADDRESS; index++ ) {
            try {
                octetValue = Integer.valueOf(stringAddress[index]);
                if ( octetValue < 0 && octetValue > OCTET_MAX_VALUE ) {
                    throw new InvalidIpAddressException();
                }
            } catch (NumberFormatException e) {
                throw new InvalidIpAddressException();
            }
        }
    }

    private int ipToInt(String address) {
        String[] stringAddress = address.split("\\.");
        int ip = 0;
        int octetValue = 0;

        for ( int index = 0; index < OCTETS_IN_ADDRESS; index++ ) {
            octetValue = Integer.valueOf(stringAddress[index]);
            ip += octetValue << ((OCTETS_IN_ADDRESS - index - 1) * BITS_IN_BYTE);
        }
        return ip;
    }

    private String ipToString(int address) {
        String out = "";
        int octetValue = 0;

        octetValue = hexConstants[OCTETS_IN_ADDRESS - 1] & address;
        out += octetValue;
        for ( int i = OCTETS_IN_ADDRESS - 2; i >= 0; i-- ) {
            octetValue = (hexConstants[i] & address) >> (BITS_IN_BYTE * (OCTETS_IN_ADDRESS - i - 1));
            if ( octetValue < 0 ) {
                octetValue += OCTET_MAX_VALUE + 1;
            }
            out = octetValue + "." + out;
        }
        return out;
    }


}
